package com.nwpu.server.search.service.impl;

import com.nwpu.server.search.config.ServerElasticSearchConfig;
import com.nwpu.server.search.constant.EsConstant;
import com.nwpu.server.search.service.GeneSearchService;
import com.nwpu.server.search.vo.SearchParam;
import com.nwpu.server.search.vo.SearchResult;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

/**
 * @Author: YuXingZh
 * @Date: Created in 18:46 2022-04-10
 * @Description:
 */

@Slf4j
@Service
public class GeneSearchServiceImpl implements GeneSearchService {

    @Autowired
    RestHighLevelClient restHighLevelClient;

    /**
     * @param param 检索的所有参数
     * @return 返回检索的结果，里面包含页面需要的所有信息
     */
    @Override
    public SearchResult search(SearchParam param) {
        SearchResult result = null;
        // 1.准备检索请求
        SearchRequest searchRequest = buildSearchRequest(param);
        try {
            // 2.执行检索请求
            SearchResponse response = restHighLevelClient.search(searchRequest, ServerElasticSearchConfig.COMMON_OPTIONS);

            // 3.分析响应数据
            result = buildSearchResult(response, param);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 构建结果数据
     * 模糊匹配，过滤（按照属性、分类、品牌，价格区间，库存），完成排序、分页、高亮,聚合分析功能
     *
     * @param response
     * @return
     */
    @Override
    public SearchResult buildSearchResult(SearchResponse response, SearchParam param) {
        SearchResult result = null;
        return result;
    }

    /**
     * 准备检索请求
     * 模糊匹配，过滤（按照属性，分类，品牌，价格区间，库存），排序，分页，高亮，聚合分析
     *
     * @return
     */
    @Override
    public SearchRequest buildSearchRequest(SearchParam param) {

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        /**
         * 模糊匹配，过滤（按照属性，分类，品牌，价格区间，库存）
         */
        //1. 构建bool-query
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        //1.1 bool-must
        if (!StringUtils.isEmpty(param.getKeyword())) {
            boolQueryBuilder.must(QueryBuilders.wildcardQuery("diseaseName", param.getKeyword()));
        }

        //1.2.5 skuPrice
        if (!StringUtils.isEmpty(param.getThreshold())) {
            //threshold：1_500或_500或500_
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("score");
            String[] threshold = param.getThreshold().split("_");
            if (threshold.length == 2) {
                rangeQueryBuilder.gte(threshold[0]).lte(threshold[1]);
            } else if (threshold.length == 1) {
                if (param.getThreshold().startsWith("_")) {
                    rangeQueryBuilder.lte(threshold[1]);
                }
                if (param.getThreshold().endsWith("_")) {
                    rangeQueryBuilder.gte(threshold[0]);
                }
            }
            boolQueryBuilder.filter(rangeQueryBuilder);
        }

        //封装所有的查询条件
        searchSourceBuilder.query(boolQueryBuilder);
        log.debug("构建的DSL语句 {}", searchSourceBuilder.toString());

        SearchRequest searchRequest = new SearchRequest(new String[]{EsConstant.GENE_DISEASE_ASSOCIATION_INDEX}, searchSourceBuilder);

        return searchRequest;
    }

    /**
     * 模糊查询
     * @param param
     * @return
     * @throws IOException
     */
    @Override
    public SearchRequest obscureSearchRequest(SearchParam param) throws IOException {
        SearchRequest searchRequest = new SearchRequest("genedisease");

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders
                .fuzzyQuery("diseasename", param.getKeyword())
                .fuzziness(Fuzziness.AUTO));
        searchRequest.source(searchSourceBuilder);
        return searchRequest;
    }
}
